﻿using System;
using System.Runtime.Serialization;

namespace Evolution.UI.WebParts
{
    [Serializable]
    public class AssertionElement : ISerializable
    {
        #region Fields

        private BaseAssertion _assertion;
        // Boolean operator that connects the current assertion to the previous one in the AssertionList.
        // The first assertion has no previous assertion.
        internal BooleanOperators _operator;

        private Condition _parent;

        #endregion

        #region Constructors

        internal AssertionElement(Condition parent, BooleanOperators op, BaseAssertion assertion)
        {
            if (parent == null)
                throw new ArgumentNullException("parent");

            if (assertion == null)
                throw new ArgumentNullException("assertion");

            this._parent = parent;
            this._assertion = assertion;
            this._operator = op;
        }

        internal AssertionElement(Condition parent, BaseAssertion assertion)
            : this(parent, BooleanOperators.None, assertion)
        {
        }

        protected AssertionElement(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new System.ArgumentNullException("info");

            this._operator = (BooleanOperators)info.GetValue("BooleanOperator", typeof(BooleanOperators));
            this._assertion = (BaseAssertion)info.GetValue("Assertion", typeof(BaseAssertion));
        }

        #endregion

        #region Properties

        public Condition Parent
        {
            get { return this._parent; }
            internal set { this._parent = value; }
        }

        public BaseAssertion Assertion
        {
            get { return this._assertion; }
            internal set { this._assertion = value; }
        }

        public BooleanOperators Operator
        {
            get { return this._operator; }
            set
            {
                if (value == BooleanOperators.None)
                    throw new InvalidOperationException();

                if (this.Parent != null)
                {
                    int index = this.Parent.List.IndexOf(this);
                    if (index == 0)
                        throw new ArgumentException("The first assertion of the list does not have a previous assertion.");
                }
                this._operator = value;
            }
        }

        #endregion

        #region Cast operators

        public static implicit operator BaseAssertion(AssertionElement c)
        {
            return c.Assertion;
        }

        public static implicit operator BooleanOperators(AssertionElement c)
        {
            return c.Operator;
        }

        #endregion

        #region Methods

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new System.ArgumentNullException("info");

            info.AddValue("BooleanOperator", this._operator);
            info.AddValue("Assertion", this._assertion);
        }

        #endregion
    }
}
